package com.example.mobiledatapackage.ontology;

import com.example.mobiledatapackage.domain.AppSeries;
import com.example.mobiledatapackage.domain.Package;
import com.example.mobiledatapackage.request.UserStatus;
import com.example.mobiledatapackage.service.AppSeriesService;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.Seq;
import org.apache.jena.vocabulary.RDF;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;


/**
 * 用于将某个对象转换成以 RDF 形式的表示
 */
@Component
public class RdfConvertor {

    @Autowired
    private AppSeriesService appSeriesService;

    /**
     * 将我们从数据库中得到的数据转换成 RDF 形式并存在一个 Jena model 中
     * @param packages 业务套餐数据
     * @return 存放了转换成 RDF 的 Jena model
     */
    public Model convertPackages(List<Package> packages, Model model) {
        Resource packageType = model.createResource(String.valueOf(RdfType.Package));
        for (Package p: packages) {
            String packageUri = UriConvertor.convertPackage(p.getId());
            Resource pkg = model.createResource(packageUri, packageType);
            // TODO:当数据库中 package 中数据有 NULL 时，这里 addLiteral 方法会产生 NPE 异常
            pkg.addProperty(OntProp.hasId, p.getId());
            pkg.addProperty(OntProp.hasName, p.getName());
            pkg.addLiteral(OntProp.generation, p.getGeneration());
            pkg.addLiteral(OntProp.baseCharge, p.getBaseCharge());
            pkg.addLiteral(OntProp.hasFreeDomesticData, p.getHasFreeDomesticData());
            pkg.addLiteral(OntProp.hasFreeOverseaData, p.getHasFreeOverseaData());
            pkg.addLiteral(OntProp.domesticDataExtraCharge, p.getDomesticDataExtraCharge());
            pkg.addLiteral(OntProp.overseaDataExtraCharge, p.getOverseaDataExtraCharge());
            pkg.addLiteral(OntProp.hasFreeDomesticVoiceCall, p.getHasFreeDomesticVoiceCall());
            pkg.addLiteral(OntProp.hasFreeOverseaVoiceCall, p.getHasFreeOverseaVoiceCall());
            pkg.addLiteral(OntProp.domesticVoiceCallExtraCharge, p.getDomesticVoiceCallExtraCharge());
            pkg.addLiteral(OntProp.overseaVoiceCallExtraCharge, p.getOverseaVoiceCallExtraCharge());
            pkg.addLiteral(OntProp.hasFreeDomesticVoiceRecv, p.getHasFreeDomesticVoiceRecv());
            pkg.addLiteral(OntProp.hasFreeOverseaVoiceRecv, p.getHasFreeOverseaVoiceRecv());
            pkg.addLiteral(OntProp.domesticVoiceRecvExtraCharge, p.getDomesticVoiceRecvExtraCharge());
            pkg.addLiteral(OntProp.overseaVoiceRecvExtraCharge, p.getOverseaVoiceRecvExtraCharge());
            pkg.addLiteral(OntProp.hasFreeDomesticMsg, p.getHasFreeDomesticMsg());
            pkg.addLiteral(OntProp.hasFreeOverseaMsg, p.getHasFreeOverseaMsg());
            pkg.addLiteral(OntProp.domesticMsgExtraCharge, p.getDomesticMsgExtraCharge());
            pkg.addLiteral(OntProp.overseaMsgExtraCharge, p.getOverseaMsgExtraCharge());
        }
        return model;
    }

    public Model convertPackages(List<Package> packages) {
        Model model = ModelFactory.createDefaultModel();
        return this.convertPackages(packages, model);
    }

    /**
     * 将数据库中得到的数据转换成 RDF 形式
     * @param appSeriesList 存放 MyBatis 获得的所有 AppSeries 对象
     * @param model 存放 RDF 的 model
     * @return 存放了转化为 RDF 后的 model
     */
    public Model convertAppSeries(List<AppSeries> appSeriesList, Model model) {
        Resource appSeriesType = model.createResource(RdfType.AppSeries.getTypeUri());
        for (AppSeries a: appSeriesList) {
            String appSeriesUri = UriConvertor.convertAppSeries(a.getSeriesId());
            Resource appSeries = model.createResource(appSeriesUri, appSeriesType);
            appSeries.addProperty(OntProp.hasName, a.getSeriesName());
            appSeries.addProperty(OntProp.hasId, a.getSeriesId());
        }
        return model;
    }

    public Model convertAppSeries(List<AppSeries> appSeriesList) {
        Model model = ModelFactory.createDefaultModel();
        return this.convertAppSeries(appSeriesList, model);
    }

    /**
     * 将一个用户的用户状态转换成存储 RDF 的 Jena model
     * @param userId 标识唯一用户的 id
     * @return 转换后的 model
     */
    public Model convertUserStatus(UserStatus userStatus, String userId) {
        String userUri = UriConvertor.convertUser(userId);
        Model model = ModelFactory.createDefaultModel();
        Resource userType = model.createResource(RdfType.User.getTypeUri());
        Resource user = model.createResource(userUri, userType);
        user.addProperty(OntProp.currentPackage, model.createResource(RdfType.Package.val(userStatus.getPkgId())));
        user.addLiteral(OntProp.hasName, userStatus.getName());
        // 添加各指标使用情况
        user.addLiteral(OntProp.usedDomesticData, userStatus.getUsedDomesticData());
        user.addLiteral(OntProp.usedOverseaData, userStatus.getUsedOverseaData());
        user.addLiteral(OntProp.usedDomesticMsg, userStatus.getUsedDomesticMsg());
        user.addLiteral(OntProp.usedOverseaMsg, userStatus.getUsedOverseaMsg());
        user.addLiteral(OntProp.usedDomesticVoiceCall, userStatus.getUsedDomesticVoiceCall());
        user.addLiteral(OntProp.usedOverseaVoiceCall, userStatus.getUsedOverseaVoiceCall());
        user.addLiteral(OntProp.usedDomesticVoiceRecv, userStatus.getUsedDomesticVoiceRecv());
        user.addLiteral(OntProp.usedOverseaVoiceRecv, userStatus.getUsedOverseaVoiceRecv());
        // 添加用户的 APP 喜好
        Seq appPreferenceSeq = model.createSeq(UriConvertor.convertAppPreferenceSeq(userId));
        Resource appPreferenceSeqType = model.createResource(RdfType.AppPreferenceSeq.getTypeUri());
        appPreferenceSeq.addProperty(RDF.type, appPreferenceSeqType);
        String[] userPreferences = {userStatus.getAppPreference1(), userStatus.getAppPreference2(), userStatus.getAppPreference3()};
        for (int i = 0; i < userPreferences.length; i++) {
            String seriesId = userPreferences[i];
            if (seriesId == null) continue;
            Resource series = model.createResource(UriConvertor.convertAppSeries(seriesId));
            appPreferenceSeq.add(i + 1, series);
        }
        user.addProperty(OntProp.hasAppPreferenceSeq, appPreferenceSeq);
        return model;
    }
}
